Skip to content

ZOOKEEPER-5037: Add export and import commands to the CLI#2375

Open
ckrumbein wants to merge 1 commit intoapache:masterfrom
ckrumbein:ZOOKEEPER-5037
Open

ZOOKEEPER-5037: Add export and import commands to the CLI#2375
ckrumbein wants to merge 1 commit intoapache:masterfrom
ckrumbein:ZOOKEEPER-5037

Conversation

@ckrumbein
Copy link
Copy Markdown

@ckrumbein ckrumbein commented Apr 21, 2026

This PR adds two commands to the ZooKeeper CLI, export and import:

  • "export <path> <filepath>" downloads the contents of a znode to an external file.
  • "import <path> <filepath>" uploads the contents of an external file to a znode, replacing the znode's previous contents.

My team has been using both of these commands for some time. We are confident they are solid.

Copy link
Copy Markdown
Contributor

@PDavid PDavid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for this contribution. These commands work really nicely. 👍

Added some minor comments / ideas.

*/
public class ExportCommand extends CliCommand {

private static Options options = new Options();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This field can be changed to be final.

} catch (IllegalArgumentException ex) {
throw new MalformedPathException(ex.getMessage());
} catch (KeeperException|InterruptedException ex) {
throw new CliException(ex);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rather use CliWrapperException here instead of CliException because CliWrapperException provides user-friendly error messages. Other commands are using this.

For example if znode does not exits now:

[zk: 127.0.0.1:2181(CONNECTED) 1] export /zookeeper/a my_data
org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /zookeeper/a
[zk: 127.0.0.1:2181(CONNECTED) 2]

using CliWrapperException:

[zk: 127.0.0.1:2181(CONNECTED) 0] export /zookeeper/a my_data
Node does not exist: /zookeeper/a
[zk: 127.0.0.1:2181(CONNECTED) 1
Suggested change
throw new CliException(ex);
throw new CliWrapperException(ex);

}
data = (data == null) ? "null".getBytes() : data;
try {
Files.write(Paths.get(filepath), data, StandardOpenOption.CREATE);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should happen if the file already exists on disk?

At the moment with only StandardOpenOption.CREATE will append to an existing file rather than replacing it.
If you export a znode twice to the same file, you get the data concatenated. Or if you export a znode to an existing file which has longer content, it will just replace some amount of the file content from the start.

Should we rather overwrite the file? If yes, we chould use CREATE + TRUNCATE_EXISTING, or simply use the default Files.write(path, data) which creates/truncates by default.

}

public ImportCommand() {
super("import", "[-s] [-v version] path filepath");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both commands we could use the 3 arg constructor:

Suggested change
super("import", "[-s] [-v version] path filepath");
super("import", "[-s] [-v version] path filepath", options);

This would include the formatted option descriptions in the generated help output:

zk: 127.0.0.1:2181(CONNECTED) 1] import
import [-s] [-v version] path filepath
 -s         stats
 -v <arg>   version

[zk: 127.0.0.1:2181(CONNECTED) 2] export
export [-s] [-w] path filepath
 -s   stats
 -w   watch

This is what we have as in this PR:

[zk: 127.0.0.1:2181(CONNECTED) 0] import
import [-s] [-v version] path filepath
[zk: 127.0.0.1:2181(CONNECTED) 1] export
export [-s] [-w] path filepath
[zk: 127.0.0.1:2181(CONNECTED) 2

deleteall path
delquota [-n|-b|-N|-B] path
exit
export path filepath
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that you extended the documentation! 👍

Should we also include the options like so?

Suggested change
export path filepath
export [-s] [-w] path filepath

getAllChildrenNumber path
getEphemerals path
history
import path filepath
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and here:

Suggested change
import path filepath
import [-s] [-v version] path filepath

Download the contents of a znode to an external file

```bash
[zkshell: 1] export /zookeeper/config path/to/config.txt
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could add here what the options are doing, like what we have for get here:
https://github.com/apache/zookeeper/blob/master/zookeeper-docs/src/main/resources/markdown/zookeeperCLI.md?plain=1#L206

@PDavid
Copy link
Copy Markdown
Contributor

PDavid commented Apr 24, 2026

Checkstyle identified some formatting problems in the build:

02:52:13  [INFO] There are 8 errors reported by Checkstyle 8.39 with checkstyle-strict.xml ruleset.
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ExportCommand.java:[28,1] (imports) ImportOrder: Extra separation in import group before 'java.io.IOException'
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ExportCommand.java:[28,1] (imports) ImportOrder: Import java.io.IOException appears after other imports that it should precede
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ExportCommand.java:[79,33] (whitespace) WhitespaceAround: '|' is not followed by whitespace.
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ExportCommand.java:[79,33] (whitespace) WhitespaceAround: '|' is not preceded with whitespace.
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ImportCommand.java:[28,1] (imports) ImportOrder: Extra separation in import group before 'java.io.IOException'
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ImportCommand.java:[28,1] (imports) ImportOrder: Import java.io.IOException appears after other imports that it should precede
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ImportCommand.java:[90,33] (whitespace) WhitespaceAround: '|' is not followed by whitespace.
02:52:13  [ERROR] src/main/java/org/apache/zookeeper/cli/ImportCommand.java:[90,33] (whitespace) WhitespaceAround: '|' is not preceded with whitespace.

https://ci-hadoop.apache.org/job/zookeeper-precommit-github-pr/job/PR-2375/1/console

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants